//
//  SYDCLLocationManager.m
//  PinGJByOwnerSide
//
//  Created by lantaiyuan on 2017/9/5.
//  Copyright © 2017年 lantaiyuan. All rights reserved.
//

#import "SYDCLLocationManager.h"

@interface SYDCLLocationManager ()<AMapLocationManagerDelegate,AMapSearchDelegate>
@property (nonatomic, strong) AMapSearchAPI *search;
@end
@implementation SYDCLLocationManager
#pragma mark - Lazy
- (AMapSearchAPI *)search{
    if (!_search) {
        _search = [[AMapSearchAPI alloc] init];
        _search.delegate = self;
        //查询超时时间，单位秒，默认为20秒
        _search.timeout = 15;
    }
    return _search;
}
+(instancetype)sharedManager{
    static SYDCLLocationManager *instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[SYDCLLocationManager alloc]init];
    });
    return instance;
}
- (instancetype)init
{
    self = [super init];
    if ( self )
    {
        self.minSpeed = 1;
        self.minFilter = 5;
        self.minInteval = 10;
        
        self.delegate = self;//设置代理
        self.distanceFilter  = self.minFilter;//定位距离
        //设置定位的精准度，一般精准度越高，越耗电（这里设置为精准度最高的，适用于导航应用）
        self.desiredAccuracy = kCLLocationAccuracyBest;
        // 定位超时时间，最低2s，此处设置为11s
        self.locationTimeout = 4;
        // 逆地理请求超时时间，最低2s，此处设置为12s
        self.reGeocodeTimeout = 4;
        //是否允许后台定位,默认为NO
        self.allowsBackgroundLocationUpdates = YES;
        //连续定位是否返回逆地理信息，默认NO
        [self setLocatingWithReGeocode:YES];
        //开始定位，不断调用其代理方法
        [self startUpdatingLocation];
    }
    return self;
}


#pragma mark - AMapLocationManagerDelegate
- (void)amapLocationManager:(AMapLocationManager *)manager didFailWithError:(NSError *)error
{
    //定位错误
    NSLog(@"%s, amapLocationManager = %@, error = %@", __func__, [manager class], error);
    if (_locationFialedBlock) {
        _locationFialedBlock();
    }
}
- (void)amapLocationManager:(AMapLocationManager *)manager didUpdateLocation:(CLLocation *)location
{
    //定位结果
    //NSLog(@"location:{lat:%f; lon:%f; accuracy:%f}", location.coordinate.latitude, location.coordinate.longitude, location.horizontalAccuracy);
//    [self stopUpdatingLocation];

    [self reGeocodeWithCoordinate:location.coordinate];
}
// 逆地理编码
- (void)reGeocodeWithCoordinate:(CLLocationCoordinate2D)coordinate{

    AMapGeoPoint * location = [AMapGeoPoint locationWithLatitude:coordinate.latitude longitude:coordinate.longitude];

    AMapReGeocodeSearchRequest * request = [[AMapReGeocodeSearchRequest alloc] init];
    request.location = location;
    [self.search AMapReGoecodeSearch:request];
}

#pragma mark - AMapSearchDelegate

- (void)onReGeocodeSearchDone:(AMapReGeocodeSearchRequest *)request response:(AMapReGeocodeSearchResponse *)response{
    if (response.regeocode != nil) {
        CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(request.location.latitude, request.location.longitude);

        NSString * province = response.regeocode.addressComponent.province == nil ? @"" : response.regeocode.addressComponent.province;
        NSString * city = response.regeocode.addressComponent.city == nil ? @"" : response.regeocode.addressComponent.city;
        NSString * district = response.regeocode.addressComponent.district == nil ? @"" : response.regeocode.addressComponent.district;
        NSString * street = response.regeocode.addressComponent.streetNumber.street == nil ? @"" : response.regeocode.addressComponent.streetNumber.street;
        NSString * number = response.regeocode.addressComponent.streetNumber.number == nil ? @"" : response.regeocode.addressComponent.streetNumber.number;
        NSString * building = response.regeocode.addressComponent.building == nil ? @"" : response.regeocode.addressComponent.building;

        NSString * address = [NSString stringWithFormat:@"%@%@%@%@%@%@",province,city,district,street,number,building];
        //保存经纬度,逆地理编码地址
        if (_locationSuccessBlock) {
            _locationSuccessBlock(coordinate,address);
        }
    }
}
- (void)locationManager:(CLLocationManager *)manager
       didFailWithError:(NSError *)error
{
    if (error.code == kCLErrorDenied) {
        // 提示用户出错原因，可按住Option键点击 KCLErrorDenied的查看更多出错信息，可打印error.code值查找原因所在
    }
}
/**
 *  规则: 如果速度小于minSpeed m/s 则把触发范围设定为50m
 *  否则将触发范围设定为minSpeed*minInteval
 *  此时若速度变化超过10% 则更新当前的触发范围(这里限制是因为不能不停的设置distanceFilter,
 *  否则uploadLocation会不停被触发)
 */
- (void)adjustDistanceFilter:(CLLocation*)location
{
    //    NSLog(@"adjust:%f",location.speed);
    
    if ( location.speed < self.minSpeed )
    {
        if ( fabs(self.distanceFilter-self.minFilter) > 0.1f )
        {
            self.distanceFilter = self.minFilter;
        }
    }
    else
    {
        CGFloat lastSpeed = self.distanceFilter/self.minInteval;
        
        if ( (fabs(lastSpeed-location.speed)/lastSpeed > 0.1f) || (lastSpeed < 0) )
        {
            CGFloat newSpeed  = (int)(location.speed+0.5f);
            CGFloat newFilter = newSpeed*self.minInteval;
            
            self.distanceFilter = newFilter;
        }
    }
}

/**
 *  授权状态发生改变时调用
 *
 *  @param manager 位置管理者
 *  @param status  状态
 */
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status{
    switch (status) {
        case kCLAuthorizationStatusNotDetermined:// 用户还没决定
        {
            NSLog(@"用户还未决定");
            if (_locationFialedBlock) {
                _locationFialedBlock();
            }
            
        }
            break;
        case kCLAuthorizationStatusRestricted: // 访问受限
        {
            NSLog(@"访问受限");
            if (_locationFialedBlock) {
                _locationFialedBlock();
            }
            
        }
            break;
        case kCLAuthorizationStatusDenied:// 定位关闭时和对此APP授权为never时调用
        {
            if ([CLLocationManager locationServicesEnabled]) {
                NSLog(@"定位已开启，但被用户拒绝");
            } else {
                NSLog(@"定位关闭，不可用");
            }
            
            if (_locationFialedBlock) {
                _locationFialedBlock();
            }
            
            if (_locationBlock) {
                _locationBlock([CLLocationManager locationServicesEnabled]);
            }
        }
            break;
        case kCLAuthorizationStatusAuthorizedAlways:// 获取前后台定位授权
        {
            NSLog(@"获取前后台定位授权");
            if (_locationFialedBlock) {
                _locationFialedBlock();
            }
        }
            break;
        case kCLAuthorizationStatusAuthorizedWhenInUse:// 获得前台定位授权
        {
            NSLog(@"获取前台定位授权");
            if (_locationFialedBlock) {
                _locationFialedBlock();
            }
        }
            break;
            
        default:
            break;
    }
}
- (void)openLocationServicesSetting:(UIViewController *)vc codeString:(NSString *)codeString{
    // 弹框提示
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"温馨提示" message:[CLLocationManager locationServicesEnabled] ? @"您的应用暂未开启定位服务!" : @"您的设备暂未开启定位服务!" preferredStyle:UIAlertControllerStyleAlert];
    [alertController addAction:[UIAlertAction actionWithTitle:@"设置" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        NSLog(@"--->确定");
        //定位服务设置界面
        NSURL *url = [NSURL URLWithString:codeString];
        if ([[UIApplication sharedApplication] canOpenURL:url])
        {
            [[UIApplication sharedApplication] openURL:url];
        }
    }]];
    
    [alertController addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        NSLog(@"--->取消");
    }]];
    
    [vc presentViewController:alertController
                     animated:YES
                   completion:nil];
}

// 单次定位
- (void)locationWithReGeocode:(AMapLocatingCompletionBlock)completionBlock{
    //带逆地理的单次定位
    [self requestLocationWithReGeocode:YES completionBlock:^(CLLocation *location, AMapLocationReGeocode *regeocode, NSError *error) {
        completionBlock(location, regeocode, error);
    }];
}
//开始单次定位
- (void)startOnceLocation{
    
    WEAKSELF
    [self requestLocationWithReGeocode:YES completionBlock:^(CLLocation *location, AMapLocationReGeocode *regeocode, NSError *error) {
        
        if (error) {
            NSLog(@"单次定位异常的error:%@,经纬度:---%f------%f",error,location.coordinate.latitude,location.coordinate.longitude);
        }else{
            
            //存在逆地理信息
            NSLog(@"单次定位成功,得到的城市:%@,GPS坐标:%f--%f,位置:%@--%@",regeocode.city,location.coordinate.latitude,location.coordinate.longitude,regeocode.POIName,regeocode.adcode);
            if (regeocode) {
                
                if (_locationSuccessBlock) {
                    weakSelf.locationSuccessBlock(location.coordinate, regeocode.POIName);
                }
            }else{
                
                if (_locationFialedBlock) {
                    weakSelf.locationFialedBlock();
                }
            }
        }
    }];
}

@end


















